# 函数

"""
def 函数名(参数):
    代码1
    代码2
    .....
"""
from functools import reduce
from typing import List

#
# # 创建一个求绝对值的函数
# def my_abs(num):
#     """
#     该函数，可以返回一个数字的绝对值
#     :param num: 传入的数字，必须是数字，且必传
#     :return: 返回该数字的绝对值
#     """
#     if num < 0:
#         return -num
#     else:
#         return num
#
#
# # 调用函数
# print(my_abs(-9))
#
#
# def new_abs(num: int) -> int:
#     """
#     Python3.5之后，可以对函数入参和返回值进行类型声明
#     该函数，可以返回一个数字的绝对值
#     :param num: 传入的数字，必须是数字，且必传
#     :return: 返回该数字的绝对值
#     """
#     if num < 0:
#         return -num
#     else:
#         return num

#
# print(new_abs(-9))

# 1.必要参数
# def test1(x, y, z):
#     return x + y + z
#
#
# # print(test1(10, 20))
#
# 2.关键字传参
# # 若存在位置参数，那么位置参数必须在关键字参数的前面
# print(test1(10, z=30, y=20))

# 3.默认值参数
# def test2(x, y, init_sum=10):
#     return init_sum + x + y
#
#
# # 不传入 init_sum
# print(test2(10, 20))
# # 传入 init_sum
# print(test2(10, 20, 50))

# 4.不定长参数
# 4.1 不定长普通参数
# def test3(*args, init_sum=10):
#     print(type(args))  # args实际就是一个元组
#     if args:
#         return init_sum + sum(args)
#     return init_sum
#
#
# print(test3())
# print(test3(10, 20, 30, init_sum=40))

# 不定长关键字参数
# def test4(init_sum=10, **kwargs):
#     print(type(kwargs))
#     for k, v in kwargs.items():
#         print(f'参数的名字：{k}，参数的值：{v}')
#     return init_sum + sum(kwargs.values())
#
#
# print(test4(x=10, y=20, z=30))

# def test5(a, b, c=100, *args, **kwargs):
#     pass

# 函数的返回值
# def test6():
#     print('hello world')
#     return
#
# print(test6())

# def test7(x, y):
#     x2 = x ** 2
#     y2 = y ** 2
#     return x2, y2
#
#
# result = test7(3, 4)
# r1, r2 = test7(3, 4)
# print(result, type(result))
# print(f'r1={r1}, r2={r2}')

# # 全局变量&局部变量
# a = 10  # 全局变量
#
#
# def test1():
#     b = 20  # 局部变量
#     return a + b
#
#
# print(test1())
# a = 10
#
#
# def test2():
#     global a   # 声明a取全局变量
#     a = 100  # 对全局变量a进行修改
#     print(a)
#     return a
#
#
# test2()
# print(a)

# def test(a, list1=[1, 2]):
#     # 把a添加到列表中
#     if a not in list1:
#         list1.append(a)
#     return list1
#
#
# print(f'函数第一次调用：{test(10)}')  # 1,2,10
# print(f'函数第二次调用：{test(20)}')  # 1,2,20 ?? 正确的是 1,2,10,20
#
# print(f'函数第三次调用：{test(30, list1=[60, 70])}')  # 60,70,30
# print(f'函数第四次调用：{test(40)}')  # 1,2,10,20,40


# def factorial(n: int) -> int:
#     """
#     计算一个正整数n的阶乘
#     :param n: 正整数
#     :return:
#     """
#
#     if n == 1:
#         return 1  # 递归函数退出的出口
#     return n * factorial(n - 1)
#
#
# print(factorial(5))

# lambda 参数列表: 表达式

# fn1 = lambda a, b: a + b
# print(fn1(1, 2))

# fn2 = lambda a,b : a if a>b else b
# print(fn2(100,200)
#
# 案例：给某个复杂的列表排序
# list1 = [
#     {'name': '张三', 'age': 18},
#     {'name': '李四', 'age': 38},
#     {'name': '王五', 'age': 28},
# ]
# # 根据年龄排序
# list1.sort(key=lambda item: item['age'])  # 升序排序
# print(list1)
#
# list1.sort(key=lambda item: item['age'], reverse=True)  # 降序排序
# print(list1)

# # 对任意两个数字，整理之后再求和
# def sum_num(a, b):
#     return abs(a) + abs(b)
#
#
# # 高阶函数的实现- 函数的参数是函数
# def sum_num2(a, b, f):
#     """
#
#     :param a:
#     :param b:
#     :param f:就是对两个数字整理的函数
#     :return:
#     """
#     return f(a) + f(b)
#
#
# # 通过绝对值整理之后再求和
# print(sum_num2(2, -6, abs))
# # 通过平方整理之后再求和
# print(sum_num2(2, -6, lambda n: n ** 2))

# # 函数的返回值是函数
# def sum_fun_b(*args):
#     def sum_nums():
#         sum = 0
#         for n in args:
#             sum += n
#         return sum
#
#     return sum_nums  # 注意这里返回的是函数，并不是调用之后才返回
#
#
# print(sum_fun_b(2, 4, 6, 8))
# # sum_fun_b(2,4,6,8)相当于函数名 因为sum_fun_b返回的是函数sum，要调用sum_fun_b就需要再后面带上括号
# print(sum_fun_b(2, 4, 6, 8)())

# # 内置高阶函数 map
# def fun1(n):
#     return n ** 2
#
#
# # map是一个可迭代对象,需要将其转化后才可打印出来
# print(list(map(fun1, [1, 2, 3, 4, 5, 6])))
#
# # 内置高阶函数 reduce
from functools import *

#
#
# def fun1(x, y):
#     return x + y
#
#
# print(reduce(fun1, [2, 4, 6, 8, 10], 10))

# 案例 统计字符串中每个单词出现的次数
# str1 = 'hello world python hello java python c++ hello python flask'
# # 分割单词
# list1 = str1.split(' ')
# print(list1)
# # 调用map转为为 单词:1
# new_list = list(map(lambda item: {item: 1}, list1))
# print(new_list)
#
#
# # 调用reduce实现相同单词叠加
# def func(dict1, dict2):
#     key = list(dict2.items())[0][0]  # 得到dict2中的key(单词:world)
#     value = list(dict2.items())[0][1]  # 得到dict2中的value(1)
#
#     dict1[key] = dict1.get(key, 0) + value
#     # 检查dict1中是否已有该键：
#     # 如果存在，将值累加（如dict1['hello'] += 1）。
#     # 如果不存在，创建该键并设置初始值（dict1['hello'] = 1）
#     return dict1
#
# print(reduce(func, new_list))

# 高阶函数 filter函数
# 保留偶数，去掉奇数
# def not_odd(num):
#     if num % 2 == 0:
#         return num
#
#
# list2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# print(list(filter(not_odd, list2)))

# 高阶函数 sorted 函数
list1 = [36, 5, -1, 100, -20, 99]
print(sorted(list1))  # 从小到大
print(sorted(list1, reverse=True))  # 从大到小
list2 = ['bob', 'about', 'Zoo', 'Credit']
print(sorted(list2))
